package com.cqq.common.core.util;

import java.security.MessageDigest;

import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <h3>摘要算法工具类</h3>
 *
 * <p>
 * 包括MD5、SHA等常用的摘要算法，计算结果以小写输出
 * </p>
 * 
 * @author xijq
 * @version 1.0.0
 * 
 */
public final class DigestUtil {

	/**
	 * 摘要算法：SHA256
	 */
	public static final String SHA256 = "SHA-256";
	
	/**
	 * 摘要算法：SHA384
	 */
	public static final String SHA384 = "SHA-384";
	
	/**
	 * 摘要算法：SHA512
	 */
	public static final String SHA512 = "SHA-512";
	
	/**
	 * 摘要算法：MD5
	 */
	public static final String MD5 = "MD5";
	
	/**
	 * 默认字符集：utf-8
	 */
	public static final String DEFAULT_CHARSET="utf-8";
	
	private static final Logger log = LoggerFactory.getLogger(DigestUtil.class);
	
	/**
	 * <h3>指定摘要算法计算</h3>
	 * 
	 * @param source 需要计算摘要的字符串
	 * @param algorithm 算法名称
	 * @param charset 字符集编码
	 * 
	 * @return String 摘要计算结果字符串
	 * @throws Exception 异常类
	 */
	public static String digest(String source, String algorithm, String charset) throws Exception {
		if(algorithm==null){
			algorithm = MD5;
		}
		MessageDigest md = MessageDigest.getInstance(algorithm);
		md.update(source.getBytes(charset));
		byte[] bytes = md.digest();
		if(algorithm.equalsIgnoreCase(MD5)){
			return new String(Hex.encode(bytes));
		}
		return new String(Base64.encode(bytes));
	}

	/**
	 * <h3>按默认UTF-8字符集编码，指定摘要算法进行计算</h3>
	 * 
	 * @param source 需要计算摘要的字符串
	 * @param algorithm 算法名称
	 * 
	 * @return String 摘要计算结果字符串
	 * @throws Exception 异常类
	 */
	public static String digest(String source, String algorithm) throws Exception {
		return digest(source, algorithm, DEFAULT_CHARSET);
	}
	
	/**
	 * <h3>按默认UTF-8字符集编码，MD5算法进行摘要计算</h3>
	 * 
	 * @param source 需要计算摘要的字符串
	 * 
	 * @return String 摘要计算结果字符串
	 * @throws Exception 异常类
	 */
	public static String digest(String source) throws Exception {
		return digest(source,null);
	}
	
	/**
	 * <h3>按默认UTF-8字符集编码，MD5算法进行摘要计算</h3>
	 * 
	 * @param source 需要计算摘要的字符串
	 * 
	 * @return String 摘要计算结果字符串
	 * @throws Exception 异常类
	 */
	public static String md5(String source) throws Exception {
		return digest(source, MD5, DEFAULT_CHARSET);
	}
	
	/**
	 * <h3>指定字符集编码进行MD5摘要计算</h3>
	 * 
	 * @param source 需要计算摘要的字符串
	 * @param charset 字符集编码
	 * 
	 * @return String 摘要计算结果字符串
	 * @throws Exception 异常类
	 */
	public static String md5(String source, String charset) throws Exception {
		return digest(source, MD5, charset);
	}
	
	public static void main(String[] args) throws Exception {
		String source = "测试字符串:test,123!";
		log.debug("明文：{}",source);
		
		String digest = DigestUtil.digest(source,DigestUtil.SHA256);
		log.debug("SHA256摘要：{}",digest);
		log.debug("SHA256摘要长度：{}",digest.length());
		
		digest = DigestUtil.digest(source,DigestUtil.SHA512);
		log.debug("SHA512摘要：{}",digest);
		log.debug("SHA512摘要长度：{}",digest.length());
		
		digest = DigestUtil.md5(source);
		log.debug("MD5摘要：{}",digest);
		log.debug("MD5摘要长度：{}",digest.length());
	}
}